package com.rgst.utils;

import java.io.OutputStream;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.util.CollectionUtils;
import com.rgst.anno.ExcelData;


/**
 * Created by tancw on 2015/8/24.
 */
public class ExportUtil {

	/**
	 * 数据表格生成
	 * 
	 * @param response
	 * @param fileName
	 *            导出文件名
	 * @param data 查询结果集
	 * @param clazz
	 *            实体类
	 * @param sheetname
	 *            表单名
	 */
	public static void exportSimpExcel(HttpServletResponse response, String fileName, List data, Class clazz, String sheetname) {
		OutputStream out = null;
		try {
			response.setCharacterEncoding("utf-8");
			response.setContentType("multipart/form-data");
			response.setHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes("utf-8"),"iso8859-1"));
			Workbook workbook = handleDataToExcel(data, clazz, sheetname);
			out = response.getOutputStream();
			workbook.write(out);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 获取表格头部与表格数据,返回表格对象
	 * 
	 * @param data
	 * @param clazz
	 * @param sheetname
	 * @return
	 * @throws Exception
	 */
	private static Workbook handleDataToExcel(List data, Class clazz, String sheetname) throws Exception {
		List<ExcelHeader> headers = getHeaderList(clazz);
		// 按order排序
		Collections.sort(headers);

		List<String> headLst = new ArrayList<String>();
		for (ExcelHeader head : headers) {
			headLst.add(head.getTitle());
		}

		String headAry[] = headLst.toArray(new String[headers.size()]);
		List<List<String>> contentLst = new ArrayList<List<String>>();

		for (Object obj : data) {
			List<String> col = new ArrayList<String>();
			for (ExcelHeader head : headers) {
				Method method = clazz.getDeclaredMethod(head.getMethodName());
				Object value = method.invoke(obj);
				if (value instanceof BigDecimal) {
					col.add(((BigDecimal) value).toPlainString());
				} else if (value instanceof Date) {
                    col.add(new SimpleDateFormat(head.getFormat()).format((Date)value));
				} else {
					col.add(String.valueOf(value));
				}
			}
			contentLst.add(col);
		}

		return getExcelWork(sheetname, headAry, contentLst);
	}

	/**
	 * 根据表格名，表格头，表格内容获取表格work
	 * 
	 * @param sheetname
	 * @param head
	 * @param contentlst
	 * @return
	 */
	public static Workbook getExcelWork(String sheetname, String[] head, List<List<String>> contentlst) {
		ExcelSheet excelSheet = ExcelUtils2.createExcelSheet(sheetname, head, contentlst);
		List<ExcelSheet> sheetList = new ArrayList<ExcelSheet>();
		sheetList.add(excelSheet);
		ExcelEntity excelEntity = new ExcelEntity();
		excelEntity.setSheetList(sheetList);
		return ExcelUtils2.writeExcel2003(excelEntity);
	}

	/**
	 * 根据注解获取表格对象
	 * @param clazz
	 * @return
	 */
	private static List<ExcelHeader> getHeaderList(Class clazz) {
		//优先匹配属性上的
		List<ExcelHeader> headers = matchField(clazz);
		if(!CollectionUtils.isEmpty(headers)) return headers;
		//属性匹配不上匹配方法
		return  matchMethod(clazz);
	}

	/**
	 * 根据class获取注解在属性上的信息
	 * @param clazz
	 * @return
     */
	private static List<ExcelHeader> matchField(Class clazz){
		List<ExcelHeader> headers = new ArrayList<ExcelHeader>();
		java.lang.reflect.Field[] fs = clazz.getDeclaredFields();
		for (java.lang.reflect.Field f : fs){
             if(f.isAnnotationPresent(ExcelData.class)){
				 ExcelData dataMapper = f.getAnnotation(ExcelData.class);
				 String getName = String.format("get%s%s",f.getName().substring(0,1).toUpperCase(),f.getName().substring(1));
				 headers.add(new ExcelHeader(dataMapper.title(), dataMapper.order(), dataMapper.format(), getName));
			 }
		}
		return headers;
	}

	/**
	 * 根据class获取注解在方法上的信息
	 * @param clazz
	 * @return
     */
	private static List<ExcelHeader> matchMethod(Class clazz) {
		List<ExcelHeader> headers = new ArrayList<ExcelHeader>();
		Method[] ms = clazz.getDeclaredMethods();
		for (Method m : ms) {
			String mn = m.getName();
			if (mn.startsWith("get")) {
				if (m.isAnnotationPresent(ExcelData.class)) {
					ExcelData dataMapper = m.getAnnotation(ExcelData.class);
					headers.add(new ExcelHeader(dataMapper.title(), dataMapper.order(), dataMapper.format(), mn));
				}
			}
		}
		return headers;
	}
}
